<template>
    <div>
        <el-upload multiple :action="uploadImgUrl" ref="uploadRef" :disabled="disabled" list-type="picture-card"
            :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload" :limit="limit"
            :on-error="handleUploadError" :on-exceed="handleExceed" name="file" :on-remove="handleRemove"
            :show-file-list="true" :headers="headers" v-model:file-list="fileArr" :on-preview="handlePictureCardPreview"
            :class="{ disabled: fileComputed }">
            <el-icon class="avatar-uploader-icon">
                <Plus />
            </el-icon>
        </el-upload>
        <!-- 上传提示 -->
        <div class="el-upload__tip" v-if="showTip">
            请上传
            <template v-if="fileSize">
                大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
            </template>
            <template v-if="fileType">
                格式为 <b style="color: #f56c6c">{{ fileType }}</b>
            </template>
            的图片
        </div>

        <el-dialog v-model="dialogVisible" title="预览" width="800px" append-to-body>
            <img :src="dialogImageUrl" style="display: block; width: 100%; margin: 0 auto" />
        </el-dialog>
    </div>
</template>
   
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'

const storage = useStorage()
const headers = ref({
    "Authorization": `Bearer ${storage.get(CacheEnum.TOKEN_NAME)}`
})
const props = defineProps({
    // 数量限制
    limit: {
        type: Number,
        default: 4,
    },
    // 大小限制(MB)
    fileSize: {
        type: Number,
        default: 10,
    },
    // 文件类型, 例如'png', 'jpg', 'jpeg',字符串，英文逗号隔开
    fileType: {
        type: String,
        default: ".png,.jpg,.jpeg",
    },
    // 请求的url
    uploadImgUrl: {
        type: String,
        default: `${import.meta.env.VITE_API_BASE_URL}/api/upload`
    },
    // 是否显示提示
    isShowTip: {
        type: Boolean,
        default: true,
    },
    // 图片数组
    fileList: {
        type: Array,
        required: false,
        default: []
    },
    // 照片墙盒子的宽度
    fileWidth: {
        type: String,
        default: '146px'
    },
    // 照片墙盒子的高度
    fileHeight: {
        type: String,
        default: '146px'
    },
    disabled: {
        type: Boolean,
        default: false,
    }
})

const emit = defineEmits(['fresh']);
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize));
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const fileArr = ref([])

// 上传超过数量限制，显示上传按钮
const fileComputed = computed(() => fileArr.value?.length == props.limit)

onMounted(() => {
})
const randomStr = () => {
    return Math.random().toString(36).substr(2)
}
watch(() => props.fileList,
    (newNum, oldNum) => {
        fileArr.value = newNum.map(item => {
            return {
                uid: randomStr(),
                status: 'done',
                name: `file-${randomStr()}`,
                url: item
            }
        })
    },
    {
        // 开启深度监听
        deep: true,
    })
// 上传前检验文件类型和文件大小
const handleBeforeUpload = (file) => {
    // 检验文件类型
    let arr = props.fileType.split(',')
    if (arr.length) {
        let str = '.' + file.name.match(/\.([^.]+)$/)[1].toLowerCase()  //匹配格式
        const isTypeOk = arr.some((type) => {
            if (str.indexOf(type) > -1) return true
            return false
        })
        if (!isTypeOk) {
            ElMessage.error(`文件格式不正确, 请上传${props.fileType}格式的图片!`)
            return false
        }

    }

    // 检验文件大小
    if (props.fileSize) {
        const isLt = file.size / 1024 / 1024 < props.fileSize;
        if (!isLt) {
            ElMessage.error(`上传文件大小不能超过 ${props.fileSize} MB!`)
            return false;
        }
    }
    return true
}

// 上传失败的提示
const handleUploadError = () => {
    ElMessage.error(`图片上传失败!`)
}

// 上传超过限制
const handleExceed = () => {
    ElMessage.error(`上传文件数量不能超过 ${props.limit} 个!`)
}

// 上传成功的回调
const handleUploadSuccess = (response, file, fileList) => {
    // console.log(fileArr.value)
    //重新构造
    emit("fresh", fileList)
}

// 删除图片的回调
const handleRemove = (file, fileList) => {

    emit("fresh", fileList)
}

// 预览图片的回调
const handlePictureCardPreview = (file) => {
    dialogImageUrl.value = file.url;
    dialogVisible.value = true;
}
const uploadRef = ref(null)
defineExpose({
    uploadRef,
    fileArr
})
</script>
   
<style lang="scss" scoped>
.disabled :deep(.el-upload--picture-card) {
    display: none
}

:deep(.el-upload-list__item-actions) {
    width: v-bind('props.fileWidth') !important;
    height: v-bind('props.fileHeight') !important;
}

:deep(.el-upload--picture-card) {
    width: v-bind('props.fileWidth') !important;
    height: v-bind('props.fileHeight') !important;
}

:deep(.el-upload-list__item) {
    width: v-bind('props.fileWidth') !important;
    height: v-bind('props.fileHeight') !important;
}
</style>